// lib/api-client.ts
// 统一的 API 客户端实现

/**
 * 获取 API 基础 URL
 */
const getApiBaseUrl = () => {
  const envApiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
  
  // 如果是生产环境且API_URL为空或http://localhost，则返回空字符串使用相对路径
  if (process.env.NODE_ENV === 'production' && (envApiUrl === 'http://localhost' || envApiUrl === '')) {
    return ''
  }
  
  return envApiUrl
}

/**
 * Token 管理器 - 统一的 token 管理
 */
export class TokenManager {
  private static ACCESS_TOKEN_KEY = 'access_token'
  private static REFRESH_TOKEN_KEY = 'refresh_token'

  static getAccessToken(): string | null {
    if (typeof window !== 'undefined') {
      return localStorage.getItem(this.ACCESS_TOKEN_KEY)
    }
    return null
  }
  
  static setAccessToken(token: string): void {
    if (typeof window !== 'undefined') {
      localStorage.setItem(this.ACCESS_TOKEN_KEY, token)
    }
  }
  
  static getRefreshToken(): string | null {
    if (typeof window !== 'undefined') {
      return localStorage.getItem(this.REFRESH_TOKEN_KEY)
    }
    return null
  }
  
  static setRefreshToken(token: string): void {
    if (typeof window !== 'undefined') {
      localStorage.setItem(this.REFRESH_TOKEN_KEY, token)
    }
  }
  
  static clearTokens(): void {
    if (typeof window !== 'undefined') {
      localStorage.removeItem(this.ACCESS_TOKEN_KEY)
      localStorage.removeItem(this.REFRESH_TOKEN_KEY)
    }
  }
  
  static setTokens(accessToken: string, refreshToken: string): void {
    this.setAccessToken(accessToken)
    this.setRefreshToken(refreshToken)
  }
}

/**
 * API 错误类
 */
export class ApiError extends Error {
  constructor(
    message: string,
    public status?: number,
    public data?: any
  ) {
    super(message)
    this.name = 'ApiError'
  }

  get isAuthError(): boolean {
    return this.status === 401
  }
}

/**
 * 请求数据类型
 */
type RequestData = Record<string, unknown> | FormData | null

/**
 * 统一的 API 客户端
 */
export class ApiClient {
  private baseURL: string

  constructor() {
    this.baseURL = getApiBaseUrl()
  }

  /**
   * 核心请求方法
   */
  private async request<T = unknown>(
    endpoint: string,
    options: RequestInit & { requireAuth?: boolean } = {}
  ): Promise<T> {
    const { requireAuth = true, ...requestOptions } = options
    const url = `${this.baseURL}${endpoint}`
    const accessToken = TokenManager.getAccessToken()
    
    const config: RequestInit = {
      ...requestOptions,
      headers: {
        ...(accessToken && requireAuth && { Authorization: `Bearer ${accessToken}` }),
        ...requestOptions.headers,
      },
    }

    try {
      const response = await this.makeRequest(url, config)
      return this.handleResponse<T>(response, url, config)
    } catch (error) {
      console.error('API request failed:', error)
      throw error
    }
  }

  /**
   * 发送请求
   */
  private async makeRequest(url: string, config: RequestInit): Promise<Response> {
    return fetch(url, config)
  }

  /**
   * 处理响应
   */
  private async handleResponse<T>(
    response: Response,
    url: string,
    config: RequestInit
  ): Promise<T> {
    // 如果是 401 错误，尝试刷新 token
    if (response.status === 401 && TokenManager.getAccessToken()) {
      const refreshed = await this.refreshAccessToken()
      if (refreshed) {
        // 重新发送原请求
        const newAccessToken = TokenManager.getAccessToken()
        const retryConfig = {
          ...config,
          headers: {
            ...config.headers,
            Authorization: `Bearer ${newAccessToken}`,
          },
        }
        const retryResponse = await this.makeRequest(url, retryConfig)
        if (!retryResponse.ok) {
          throw this.createErrorFromResponse(retryResponse, await this.getErrorData(retryResponse))
        }
        return retryResponse.json()
      } else {
        // 刷新失败，清除 token 并抛出认证错误
        TokenManager.clearTokens()
        throw new ApiError('Authentication failed', 401)
      }
    }

    if (!response.ok) {
      const errorData = await this.getErrorData(response)
      throw this.createErrorFromResponse(response, errorData)
    }

    // 如果响应为空，返回空对象
    const text = await response.text()
    if (!text) {
      return {} as T
    }

    return JSON.parse(text) as T
  }

  /**
   * 获取错误数据
   */
  private async getErrorData(response: Response): Promise<any> {
    try {
      const text = await response.text()
      if (!text) {
        return { message: `HTTP error! status: ${response.status}` }
      }
      return JSON.parse(text)
    } catch (parseError) {
      console.error('解析错误响应失败:', parseError)
      return { message: `HTTP error! status: ${response.status}` }
    }
  }

  /**
   * 从响应创建错误对象
   */
  private createErrorFromResponse(response: Response, errorData: any): ApiError {
    let errorMessage = `HTTP error! status: ${response.status}`
    
    // 如果是对象形式的错误，尝试提取具体信息
    if (typeof errorData === 'object' && errorData !== null) {
      if ('detail' in errorData) {
        errorMessage = errorData.detail
      } else if ('error' in errorData) {
        errorMessage = errorData.error
      } else if ('message' in errorData) {
        errorMessage = errorData.message
      } else {
        // 处理 DRF 序列化器验证错误
        const fieldErrors: string[] = []
        
        // 优先处理 non_field_errors
        if (errorData.non_field_errors && Array.isArray(errorData.non_field_errors)) {
          fieldErrors.push(...errorData.non_field_errors)
        }
        
        // 处理其他字段验证错误
        for (const [field, errors] of Object.entries(errorData)) {
          if (field !== 'non_field_errors') {
            if (Array.isArray(errors)) {
              fieldErrors.push(...(errors as string[]))
            } else if (typeof errors === 'string') {
              fieldErrors.push(errors)
            }
          }
        }
        
        if (fieldErrors.length > 0) {
          errorMessage = fieldErrors.join('; ')
        } else if (Object.keys(errorData).length > 0) {
          console.warn('未能解析的错误格式:', errorData)
          errorMessage = `请求失败: ${JSON.stringify(errorData)}`
        }
      }
    } else if (typeof errorData === 'string') {
      errorMessage = errorData
    }
    
    // 对于登出相关的错误，提供更友好的错误信息
    if (response.url?.includes('/logout/')) {
      if (response.status >= 500) {
        errorMessage = '服务器内部错误，登出失败'
      } else if (response.status === 401) {
        errorMessage = '登出失败：Token已失效'
      } else if (response.status === 400) {
        errorMessage = errorMessage || '登出失败：请求参数错误'
      } else {
        errorMessage = '登出失败'
      }
    }
    
    return new ApiError(errorMessage, response.status, errorData)
  }

  /**
   * 刷新访问令牌
   */
  private async refreshAccessToken(): Promise<boolean> {
    const refreshToken = TokenManager.getRefreshToken()
    if (!refreshToken) {
      return false
    }

    try {
      const response = await fetch(`${this.baseURL}/api/auth/token/refresh/`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ refresh: refreshToken }),
      })

      if (response.ok) {
        const data = await response.json()
        TokenManager.setAccessToken(data.access)
        return true
      }
      return false
    } catch (error) {
      console.error('Token refresh failed:', error)
      return false
    }
  }

  /**
   * GET 请求
   */
  async get<T = unknown>(endpoint: string, requireAuth = true): Promise<T> {
    return this.request<T>(endpoint, { method: 'GET', requireAuth })
  }

  /**
   * POST 请求
   */
  async post<T = unknown>(endpoint: string, data?: RequestData, requireAuth = true): Promise<T> {
    const isFormData = data instanceof FormData
    return this.request<T>(endpoint, {
      method: 'POST',
      requireAuth,
      ...(isFormData ? {} : { headers: { 'Content-Type': 'application/json' } }),
      body: isFormData ? data : (data ? JSON.stringify(data) : undefined),
    })
  }

  /**
   * PUT 请求
   */
  async put<T = unknown>(endpoint: string, data?: RequestData, requireAuth = true): Promise<T> {
    const isFormData = data instanceof FormData
    return this.request<T>(endpoint, {
      method: 'PUT',
      requireAuth,
      ...(isFormData ? {} : { headers: { 'Content-Type': 'application/json' } }),
      body: isFormData ? data : (data ? JSON.stringify(data) : undefined),
    })
  }

  /**
   * PATCH 请求
   */
  async patch<T = unknown>(endpoint: string, data?: RequestData, requireAuth = true): Promise<T> {
    const isFormData = data instanceof FormData
    return this.request<T>(endpoint, {
      method: 'PATCH',
      requireAuth,
      ...(isFormData ? {} : { headers: { 'Content-Type': 'application/json' } }),
      body: isFormData ? data : (data ? JSON.stringify(data) : undefined),
    })
  }

  /**
   * DELETE 请求
   */
  async delete<T = unknown>(endpoint: string, requireAuth = true): Promise<T> {
    return this.request<T>(endpoint, { method: 'DELETE', requireAuth })
  }
}

// 创建全局 API 客户端实例
export const apiClient = new ApiClient()

// 导出常用的 API 端点
export const API_ENDPOINTS = {
  // 认证相关
  checkUserType: '/api/auth/check-user-type/',
  login: '/api/auth/login/',
  logout: '/api/auth/logout/',
  refreshToken: '/api/auth/token/refresh/',
  profile: '/api/auth/profile/',
  updateProfile: '/api/auth/profile/update/',
  changePassword: '/api/auth/change-password/',
  
  // 机构和实验室
  institutions: '/api/auth/institutions/',
  laboratories: '/api/auth/laboratories/',
  
  // 项目相关
  projects: '/api/projects/',
  projectDetail: (id: string) => `/api/projects/${id}/`,
  projectAttachments: (id: string) => `/api/projects/${id}/attachments/`,
  attachmentDetail: (projectId: string, attachmentId: string) => 
    `/api/projects/${projectId}/attachments/${attachmentId}/`,
  attachmentDownload: (projectId: string, attachmentId: string) => 
    `/api/projects/${projectId}/attachments/${attachmentId}/download/`,
} as const